package edu.towson.greenteam.menu;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import edu.towson.greenteam.Collection;
import edu.towson.greenteam.Consts;
import edu.towson.greenteam.Iterator;
import edu.towson.greenteam.order.Order;

public class Menu implements Observer, Collection<MenuItem> {

    private ArrayList<MenuItem> currentMenu;
    private int lastID;

    public Menu() {
        currentMenu = new ArrayList<MenuItem>();
        lastID = 0;
    }

    // Implement methods from Collection<E> interface
    @Override
    public boolean add(MenuItem item) {
        if (this.isEmpty()) {
            currentMenu.add(item);
            item.setId(lastID++);
        } else {
            if (this.contains(item)) {
                return false;
            }
            currentMenu.add(item);
        }
        return true;
    }

    @Override
    public boolean contains(MenuItem item) {
        return currentMenu.contains(item);
    }

    @Override
    public boolean update(MenuItem item) {
        Iterator<MenuItem> i = getItr();
        MenuItem current;
        while (i.hasNext()) {
            current = i.next();
            if (current.getId() == (item.getId())) {
                current.setName(item.getName());
                current.setDescription(item.getDescription());
                current.setPrice(item.getPrice());
                current.setRating(item.getRating());
                current.setMaxQty(item.getMaxQty());
                current.setCurrentQty(item.getCurrentQty());
                current.setCategory(item.getCategory());
                current.setPrepTime(item.getPrepTime());
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean remove(MenuItem item) {
        return currentMenu.remove(item);
    }

    @Override
    public boolean isEmpty() {
        return currentMenu.isEmpty();
    }

    @Override
    public int size() {
        return currentMenu.size();
    }

    // Standard iterator
    public Iterator<MenuItem> getItr() {
        return new Itr();
    }

    // Special iterator that iterates only over menu items lower than a specified price
    public Iterator<MenuItem> getMenuPriceItr(float price) {
        return new MenuPriceItr(price);
    }

    @Override
    public String toString() {
        String menuString = "";
        if (currentMenu.isEmpty()) {
            return "There are currently no items on the menu.";
        }
        for (MenuItem mi : currentMenu) {
            menuString += mi.getName() + "\n" + mi.getDescription() + "\nPrice: $"
                    + mi.getCurrentPrice() + "\n\n";
        }
        return menuString;
    }

    /************************************************************************
     * Methods for being an OBSERVER (i.e. Menu observes Orders)
     ***********************************************************************/
    @Override
    public void update(Observable arg0, Object arg) {
        String changedClass = arg0.getClass().getCanonicalName();
        if (changedClass == Consts.ORDERS) {
            Order orderJustServed = (Order) arg;
            MenuItem itemJustServed = orderJustServed.getMenuItem();
            //5/9/12 per prof don't track quantity
            //           itemJustServed.setCurrentQty(itemJustServed.getCurrentQty()-1);
            itemJustServed.adjustPrice();
        }
    }

    // Special iterator that iterates only over menu items rated higher than or equal to
    // a specified value
    public Iterator<MenuItem> getMenuRatingItr(int rating) {
        return new MenuRatingItr(rating);
    }

    private class Itr implements Iterator<MenuItem> {

        private int current;

        public Itr() {
            this.current = 0;
        }

        @Override
        public boolean hasNext() {
            return current <= currentMenu.size() - 1;
        }

        public boolean hasPrevious() {
            return current > 0;
        }

        @Override
        public MenuItem next() {
            if (hasNext() == false) {
                return null;
            } else {
                MenuItem returnMI = currentMenu.get(current);
                current++;
                return returnMI;
//				return currentMenu.get(current++);
            }
        }

        public MenuItem previous() {
            if (hasPrevious() == false) {
                return null;
            } else {
                return currentMenu.get(--current);
            }
        }
    }

    private class MenuPriceItr implements Iterator<MenuItem> {

        private float price;
        private int current;

        public MenuPriceItr(float price) {
            this.price = price;
            this.current = 0;
        }

        @Override
        public boolean hasNext() {
            if (current >= currentMenu.size() - 1) {
                return false;
            } else {
                while (current < currentMenu.size() - 1) {
                    if (currentMenu.get(current).getCurrentPrice() <= price) {
                        return true;
                    }
                    current++;
                }
                return false;
            }
        }

        public boolean hasPrevious() {
            if (current < 1) {
                return false;
            } else {
                while (current > 0) {
                    if (currentMenu.get(--current).getCurrentPrice() <= price) {
                        return true;
                    }
                }
                return false;
            }
        }

        @Override
        public MenuItem next() {
            if (hasNext() == false) {
                return null;
            } else {
                while (current < currentMenu.size() - 1) {
                    if (currentMenu.get(current).getCurrentPrice() <= price) {
                        MenuItem currenMenuItem = currentMenu.get(current);
                        current++;
                        return currenMenuItem;
                    }
                }
                return null;
            }
        }

        public MenuItem previous() {
            if (hasPrevious() == false) {
                return null;
            } else {
                while (current > 0) {
                    if (currentMenu.get(--current).getCurrentPrice() <= price) {
                        return currentMenu.get(current);
                    }
                }
                return null;
            }
        }
    }

    private class MenuRatingItr implements Iterator<MenuItem> {

        private int rating;
        private int current = 0;

        public MenuRatingItr(int rating) {
            this.rating = rating;
        }

        @Override
        public boolean hasNext() {
            if (current >= currentMenu.size() - 1) {
                return false;
            } else {
                while (current < currentMenu.size() - 1) {
                    if (currentMenu.get(current).getRating() >= rating) {
                        return true;
                    }
                    current++;
                }
                return false;
            }
        }

        public boolean hasPrevious() {
            if (current < 1) {
                return false;
            } else {
                while (current > 0) {
                    if (currentMenu.get(--current).getRating() >= rating) {
                        return true;
                    }
                }
                return false;
            }
        }

        @Override
        public MenuItem next() {
            if (hasNext() == false) {
                return null;
            } else {
                while (current < currentMenu.size() - 1) {
                    if (currentMenu.get(current).getRating() >= rating) {
                        return currentMenu.get(current);
                    }
                    current++;
                }
                return null;
            }
        }

        public MenuItem previous() {
            if (hasPrevious() == false) {
                return null;
            } else {
                while (current > 0) {
                    if (currentMenu.get(--current).getRating() >= rating) {
                        return currentMenu.get(current);
                    }
                }
                return null;
            }
        }
    }
}
